package org.zeapp.opencloud.framework.cloud.impl.dropbox;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URI;
import java.util.Locale;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;

import org.zeapp.opencloud.framework.cloud.CloudException;
import org.zeapp.opencloud.framework.preference.CallbackHandler;
import org.zeapp.opencloud.framework.preference.Preference;

import com.dropbox.core.DbxAppInfo;
import com.dropbox.core.DbxAuthFinish;
import com.dropbox.core.DbxClient;
import com.dropbox.core.DbxRequestConfig;
import com.dropbox.core.DbxWebAuthNoRedirect;
import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;

@SuppressWarnings("serial")
public class PreferencePanel extends JPanel {
	private JTextField txtAuthorizationCode;
	private final JButton btnRetrieveToken = new JButton(
			Messages.getString("PreferencePanel.btnRetrieveToken.text")); //$NON-NLS-1$
	private JLabel lblYourAreAuthenticated;
	private JLabel lblYourAreNotAuthenticated;

	// contextual objects
	private String token;
	private CallbackHandler exceptionHandler;

	/**
	 * Create the panel.
	 */
	public PreferencePanel() {
		setLayout(new FormLayout(new ColumnSpec[] {
				FormFactory.RELATED_GAP_COLSPEC, FormFactory.PREF_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC, FormFactory.DEFAULT_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC,
				ColumnSpec.decode("default:grow"),
				FormFactory.RELATED_GAP_COLSPEC, FormFactory.DEFAULT_COLSPEC,
				FormFactory.RELATED_GAP_COLSPEC, }, new RowSpec[] {
				FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, }));

		lblYourAreNotAuthenticated = new JLabel(
				Messages.getString("PreferencePanel.lblYourAreNotAuthenticated.text")); //$NON-NLS-1$
		lblYourAreNotAuthenticated.setForeground(new Color(255, 0, 0));
		lblYourAreNotAuthenticated.setFont(new Font("Tahoma", Font.BOLD, 15));
		add(lblYourAreNotAuthenticated, "2, 2, 7, 1");

		JLabel lblDoTheFollowing = new JLabel(
				Messages.getString("PreferencePanel.lblDoTheFollowing.text")); //$NON-NLS-1$
		add(lblDoTheFollowing, "2, 6, 7, 1");

		JLabel lblGotogoogle = new JLabel(
				Messages.getString("PreferencePanel.lblGotogoogle.text")); //$NON-NLS-1$
		lblGotogoogle.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		lblGotogoogle.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				openAuthorizationUrl();
			}
		});
		add(lblGotogoogle, "4, 8, 5, 1");

		JLabel label = new JLabel(
				Messages.getString("PreferencePanel.label.text")); //$NON-NLS-1$
		add(label, "4, 10, 5, 1");

		JLabel lblNewLabel = new JLabel(
				Messages.getString("PreferencePanel.lblNewLabel.text")); //$NON-NLS-1$
		add(lblNewLabel, "4, 12, 5, 1");

		JLabel lblAuthorizationCode = new JLabel(
				Messages.getString("PreferencePanel.lblAuthorizationCode.text")); //$NON-NLS-1$
		add(lblAuthorizationCode, "4, 14, right, default");

		txtAuthorizationCode = new JTextField();
		add(txtAuthorizationCode, "6, 14, fill, default");
		txtAuthorizationCode.setColumns(10);
		btnRetrieveToken.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				retrieveAuthorizationToken();
			}
		});
		add(btnRetrieveToken, "8, 14");

		JSeparator separator = new JSeparator();
		add(separator, "2, 5, 7, 1");

		lblYourAreAuthenticated = new JLabel(
				Messages.getString("PreferencePanel.lblYourAreAuthenticated.text")); //$NON-NLS-1$
		lblYourAreAuthenticated.setForeground(new Color(50, 205, 50));
		lblYourAreAuthenticated.setFont(new Font("Tahoma", Font.BOLD, 15));
		add(lblYourAreAuthenticated, "2, 2, 7, 1");

	}

	public void initContent(Preference preference,
			CallbackHandler exceptionHandler) {
		this.exceptionHandler = exceptionHandler;
		token = preference.get(DropBoxDriver.TOKEN_KEY);
		checkConnection();
	}

	private void checkConnection() {
		if (token != null) {
			try {
				DbxRequestConfig config = new DbxRequestConfig(
						"ZeAPP Open Cloud", Locale.getDefault().toString());

				DbxClient client = new DbxClient(config, token);
				lblYourAreAuthenticated
						.setText(Messages
								.getString("PreferencePanel.lblYourAreAuthenticated.text")
								+ client.getAccountInfo().displayName);
				lblYourAreNotAuthenticated.setVisible(false);
				lblYourAreAuthenticated.setVisible(true);
				exceptionHandler.needRefresh();
			} catch (Exception e) {
				if (exceptionHandler == null) {
					e.printStackTrace();
				} else {
					exceptionHandler.exceptionOccurs(new CloudException(
							"Authentication failure.", "DROPBOX00002", e));
				}
				lblYourAreNotAuthenticated.setVisible(true);
				lblYourAreAuthenticated.setVisible(false);
			}
		} else {
			lblYourAreNotAuthenticated.setVisible(true);
			lblYourAreAuthenticated.setVisible(false);
		}

	}

	private void openAuthorizationUrl() {
		Desktop d = Desktop.getDesktop();
		try {
			DbxWebAuthNoRedirect webAuth = getWebAuth();
			String authorizeUrl = webAuth.start();

			d.browse(new URI(authorizeUrl));
		} catch (Exception e) {
			if (exceptionHandler == null) {
				e.printStackTrace();
			} else {
				exceptionHandler.exceptionOccurs(new CloudException(
						"Impossible to call the authorization url",
						"DROPBOX00001", e));
			}
		}

	}

	private void retrieveAuthorizationToken() {
		if (!"".equals(txtAuthorizationCode.getText().trim())) {
			String code = txtAuthorizationCode.getText();
			DbxWebAuthNoRedirect webAuth = getWebAuth();
			try {
				DbxAuthFinish authFinish = webAuth.finish(code);
				token = authFinish.accessToken;

			} catch (Exception e) {
				if (exceptionHandler == null) {
					e.printStackTrace();
				} else {
					exceptionHandler.exceptionOccurs(new CloudException(
							"Impossible to retrieve the authentication token.",
							"DROPBOX00003", e));
				}
			} finally {
				checkConnection();
			}
		}
	}

	private DbxWebAuthNoRedirect getWebAuth() {
		final String APP_KEY = "0c7uxjyy47rlvk9";
		final String APP_SECRET = "lk9l8hov0ltvy53";

		DbxAppInfo appInfo = new DbxAppInfo(APP_KEY, APP_SECRET);

		DbxRequestConfig config = new DbxRequestConfig("ZeAPP Open Cloud",
				Locale.getDefault().toString());
		DbxWebAuthNoRedirect webAuth = new DbxWebAuthNoRedirect(config, appInfo);
		return webAuth;
	}

	public boolean apply(Preference preference) {
		preference.set(DropBoxDriver.TOKEN_KEY, token);
		return preference.commit();
	}
}
